/* * <Manal project is an eclipse plugin for the automation of malware analysis.> * Copyright (C) <2014> <Nikolay Akatyev, Hojun Son> * This file is part of Manal project. * * Manal project is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * Manal project is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Manal project. If not, see <http://www.gnu.org/licenses/>. * * Contact information of contributors: * - Nikolay Akatyev: nikolay.akatyev@gmail.com * - Hojun Son: smuoon4680@gmail.com */ package com.dforensic.plugin.manal.parser; import com.dforensic.plugin.manal.model.ApiDescriptor; import com.dforensic.plugin.manal.model.ProjectProperties; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Statement; import java.util.ArrayList; import java.util.List; /** * Analyze a source code. * * Refer http://www.vogella.com/tutorials/EclipseJDT/article.html * http://www.eclipse * .org/articles/article.php?file=Article-JavaCodeManipulation_AST/index.html * * @author Zeoo * */ public class SuspectSearch { private List<ApiDescriptor> mMethodDetails = new ArrayList<ApiDescriptor>(); /** Methods to detect in a source code. */ private List<ApiDescriptor> mFilterMethods = null; public void run() { // Get the root of the workspace IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot root = workspace.getRoot(); // Get all projects in the workspace IProject[] projects = root.getProjects(); // Loop over all projects for (IProject project : projects) { try { String apkName = project.getPersistentProperty(new QualifiedName(ProjectProperties.QUALIFIER, ProjectProperties.getApkNameKey())); // String prjName = project.getPersistentProperty(new QualifiedName(ProjectProperties.QUALIFIER, // ProjectProperties.getPrjNameKey())); // if (project.getFullPath().toString().equals(ProjectProperties.getPrjNameVal())) { // if ((prjName != null) && prjName.equals(ProjectProperties.getPrjNameVal())) { if ((apkName != null) && apkName.equals(ProjectProperties.getApkNameVal())) { boolean res = extractProjectInfo(project); if (res) { System.out.println("The search is achieved."); return; } } else { System.out.println("Skip the project, path is not matched."); } } catch (CoreException e) { e.printStackTrace(); } } } // public void setSuspectApi(List<ApiDescriptor> apiList) { // mFilterMethods = apiList; // } public List<ApiDescriptor> getMethodDescriptions() { return mMethodDetails; } /** * If JavaElement in the project is found * for the passed API it is set as a member * for it. */ public void getJavaElementForApi(ApiDescriptor api) { mFilterMethods = new ArrayList<ApiDescriptor>(); mFilterMethods.add(api); run(); } private boolean extractProjectInfo(IProject project) throws CoreException, JavaModelException { System.out.println("Working in project " + project.getName()); // check if we have a Java project if (project.isNatureEnabled(JavaCore.NATURE_ID)) { IJavaProject javaProject = JavaCore.create(project); if (extractPackageInfos(javaProject)) { return true; } } else { System.err.println("This is not Java project."); } return false; } private boolean extractPackageInfos(IJavaProject javaProject) throws JavaModelException { IPackageFragment[] packages = javaProject.getPackageFragments(); for (IPackageFragment packageSearched : packages) { if (mFilterMethods != null) { for (ApiDescriptor api : mFilterMethods) { // Package fragments include all packages in the classpath. // We will only look at the package from the source folder. // K_BINARY would include also included JARS, e.g. rt.jar String packageName = api.getPackageNameFromSoot(); if (packageName != null) { if ((packageSearched.getKind() == IPackageFragmentRoot.K_SOURCE) && packageName.equals(packageSearched.getElementName())) { System.out.println("Package " + packageSearched.getElementName()); if (createAST(packageSearched, api)) { return true; } // extractClassInfo(mypackage); } } else { System.err.println("Package name is NULL for " + api.toString()); } } } else { System.err.println("Methods for search are not initialized. " + "mFilterMethods is NULL."); } } return false; } private boolean createAST(IPackageFragment packageSearched, ApiDescriptor methodSearched) throws JavaModelException { String className = methodSearched.getClassNameFromSoot(); if (className == null) { System.err.println("Can't search. Class name is NULL."); return false; } for (ICompilationUnit unit : packageSearched.getCompilationUnits()) { String unitName = unit.getElementName(); if ((unitName != null) && unitName.contains(className)) { // now create the AST for the ICompilationUnits final CompilationUnit parse = parse(unit); methodSearched.setCompilationUnit(parse); return true; // MethodVisitor visitor = new MethodVisitor(); // parse.accept(visitor); // // for (MethodDeclaration method : visitor.getMethods()) { // System.out.print("Method name: " + method.getName() // + " Return type: " + method.getReturnType2()); // extractStatements(parse, method, methodSearched); // } } } return false; } /** * Reads a ICompilationUnit and creates the AST DOM for manipulating the * Java source file * * @param unit * @return */ private static CompilationUnit parse(ICompilationUnit unit) { ASTParser parser = ASTParser.newParser(AST.JLS4); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setSource(unit); parser.setResolveBindings(true); return (CompilationUnit) parser.createAST(null); // parse } private void extractStatements(CompilationUnit cu, MethodDeclaration method, ApiDescriptor methodSearched) { String methodName = methodSearched.getMethodNameFromSoot(); if (methodName == null) { System.err.println("Can't search a method. Method name is NULL."); return; } Block body = method.getBody(); if (body != null) { for (Statement smt : (List<Statement>) body.statements()) { if (smt instanceof ExpressionStatement) { Expression esn = ((ExpressionStatement) smt) .getExpression(); if (esn instanceof MethodInvocation) { // TODO when refactoring // go deeper to statements (not only MethodInvoke) MethodInvocation inv = (MethodInvocation) esn; if (methodName.equals(inv.getName())) { methodSearched.setCompilationUnit(cu); return; } // filterMethod(cu, inv); // SimpleName name = inv.getName(); // ApiDescriptor apiDesc = new ApiDescriptor(); // apiDesc.setMethodName(name.getIdentifier()); // apiDesc.setReturnType(method.getReturnType()); // apiDesc.setSignature(method.getSignature()); // mMethodDetails.add(apiDesc); } } } } else { System.out.print(">>warning: the method doesn't have a body."); } } private void filterMethod(CompilationUnit cu, MethodInvocation method) { if (mFilterMethods != null) { for (ApiDescriptor desc : mFilterMethods) { if (desc.isSimilar(method)) { ApiDescriptor cloneDesc = desc.clone(method); cloneDesc.setCompilationUnit(cu); addMethodDetails(cloneDesc); } } } else { System.out .println(">>inf: the filter is not set up. Return all found methods."); ApiDescriptor cloneDesc = new ApiDescriptor(method); addMethodDetails(cloneDesc); } } /** * Add method details to the list of return methods. */ private void addMethodDetails(ApiDescriptor desc) { mMethodDetails.add(desc); } /** ==============Not used======================================== */ private void extractClassInfo(IPackageFragment mypackage) throws JavaModelException { for (ICompilationUnit unit : mypackage.getCompilationUnits()) { extractClassDetails(unit); } } private void extractClassDetails(ICompilationUnit unit) throws JavaModelException { System.out.println("Source file " + unit.getElementName()); extractMethods(unit); } private void extractMethods(ICompilationUnit unit) throws JavaModelException { IType[] allTypes = unit.getAllTypes(); for (IType type : allTypes) { extractMethodDetails(type); } } private void extractMethodDetails(IType type) throws JavaModelException { IMethod[] methods = type.getMethods(); for (IMethod method : methods) { ApiDescriptor apiDesc = new ApiDescriptor(); apiDesc.setMethodName(method.getElementName()); apiDesc.setReturnType(method.getReturnType()); apiDesc.setSignature(method.getSignature()); mMethodDetails.add(apiDesc); } } }